#include "blisp.h"

Type Pair_t;

Pair *Pair_new(Object *head, Object *tail)
{
	Pair *p = GC_NEW(Pair);
	sethead(p, head);
	settail(p, tail);
	return p;
}

Object *OPair_new(Object *head, Object *tail)
{
	Object *o = GC_NEW(Object);
	settype(o, TPAIR);
	setpair(o, Pair_new(head, tail));
	return o;
}

/*
 * TODO: FIXME: just stubbed -- need to adjust for list/function evaluation
 */
Object *Pair_eval(Object *o)
{
	return ONIL;
}

/*
 * Only handles simple pairs now
 */
const char *Pair_to_cstr(Object *o)
{
	char CONS_START = '(';
	char CONS_MIDDLE[] = " . ";
	char CONS_END[] = ")";

	const char *head = To_cstr(Pair_head(o));
	const char *tail = To_cstr(Pair_tail(o));

	int head_len = strlen(head);
	int tail_len = strlen(tail);
	int extra_len =
		sizeof(CONS_START)
		+ (sizeof(CONS_MIDDLE) - 1)
		+ (sizeof(CONS_END) - 1);
	int buffer_len = head_len + tail_len + extra_len + 1;

	char *buffer = GC_MALLOC_ATOMIC(buffer_len);
	char *bufptr = buffer;

	bufptr[0] = CONS_START;
	bufptr += sizeof(CONS_START);

	strncpy(bufptr, head, head_len);
	bufptr += head_len;

	strncpy(bufptr, CONS_MIDDLE, sizeof(CONS_MIDDLE) - 1);
	bufptr += sizeof(CONS_MIDDLE) - 1;

	strncpy(bufptr, tail, tail_len);
	bufptr += tail_len;

	strncpy(bufptr, CONS_END, sizeof(CONS_END));

	return (const char *) buffer;
}

Object *Pair_equal(Object *o1, Object *o2)
{
	return cbool_to_lbool(pair_equal(o1, o2));
}

/*
 * FIXME: is this proper compare of pairs?
 */
int pair_equal(Object *o1, Object *o2)
{
	return lbool_to_cbool(Equal_p(Head(o1), Head(o2)))
		&& lbool_to_cbool(Equal_p(Tail(o1), Tail(o2)));
}

Object *Pair_head(Object *o)
{
	if (!pair_p(o))
		return ONIL;
	return gethead(getpair(o));
}

Object *Pair_tail(Object *o)
{
	if (!pair_p(o))
		return ONIL;
	return gettail(getpair(o));
}
